package main

import (
	"errors"
	"fmt"
	"time"
)

type LoaderInter interface {
	Load()
}

func Check(li LoaderInter) error {
	ch := make(chan struct{})
	go func() {
		li.Load()
		ch <- struct{}{}
	}()
	select {
	case <-ch:
		return nil
	case <-time.After(time.Second * 5):
		return errors.New("load time out error")
	}
}

type Loader struct {
}

func (ld Loader) Load() {
	fmt.Println("Loader begin load data....")
	<-time.After(time.Second * 10)
	fmt.Println("Loader load data success...")
}

type ProducerInter interface {
	Produce() LoaderInter
}

type Producer struct {
	max int //最大产量
}

func (p *Producer) Produce() LoaderInter {
	if p.max <= 0 {
		return nil
	}

	ld := &Loader{}
	p.max--
	return ld
}

func Create(producer ProducerInter) {
	maxch := make(chan struct{}, 5)
	for {
		select {
		case maxch <- struct{}{}:
			ld := producer.Produce()
			if ld == nil {
				fmt.Println("producer end ,max ....")
				return
			}

			go func() {
				ld.Load()
				<-maxch
			}()
		}

	}
}

func main() {
	// ld := &Loader{}
	// err := Check(ld)
	// if err != nil {
	// 	fmt.Println("err is ", err)
	// }

	// time.Sleep(time.Second * 11)

	p := Producer{max: 10}
	Create(&p)
}
